/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.sipper.modeling.metabolicNetworks;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import combi.wip.sipper.modeling.Protein;
import combi.wip.sipper.modeling.reactions.FilteredReaction;
import combi.wip.sipper.modeling.reactions.Reaction;
import combi.wip.sipper.modeling.reactions.ReactionUtil;


public  class ImplOfFilteredMetabolicNetworkWithEnzymes<C,R extends Reaction<C>, E extends Protein> extends ImplOfMetabolicNetworkWithEnzymes<C,R,E> {

	protected Collection<C> filteredMetabolites; 
	protected Collection<Reaction<C>> removedReactions;

	public ImplOfFilteredMetabolicNetworkWithEnzymes(Collection<C> filteredMetabolites)
	{
		super();
		this.filteredMetabolites = new HashSet<C>(filteredMetabolites);
		this.removedReactions = new HashSet<Reaction<C>>();
	}
	
	
	public ImplOfFilteredMetabolicNetworkWithEnzymes(MetabolicNetworkWithEnzymes<C,Reaction<C>,E> meta, Collection<C> filteredMetabolites)
	{
		super();
		this.filteredMetabolites = new HashSet<C>(filteredMetabolites);
		for(C c : meta.getCompoundSet())
		{
			if(!this.filteredMetabolites.contains(c))
			{
				this.addCompound(c);
			}
		}
		for (Protein enz : meta.getEnzymeSet())
		{
			this.addEnzyme(enz);
		}
		for(Reaction<C> r : meta.getReactionSet())
		{
			Reaction<C> rf = new FilteredReaction<C>(r,this.filteredMetabolites);
			this.addReaction(rf);
			for (Protein enz : meta.getEnzymes(r))
			{
				this.addCatalyze(enz, rf);
			}
		}
		this.removedReactions = this.checkAndRemoveReactions();
	}

	public Collection<C> getRemovedMetabolites() {
		return filteredMetabolites;
	}
	public Collection<Reaction<C>> getRemovedReactions() {
		return removedReactions;
	}

	protected Collection<C> filter(Collection<C> cpds)
	{
		Set<C> result = new HashSet<C>(cpds);
		result.removeAll(this.getRemovedMetabolites());
		return result;
	}


//	@Override
//	public void addReaction(Reaction<C> r)
//	{
//		FilteredReaction<C> rf = new FilteredReaction<C>(r,this.filteredMetabolites);
//		if (rf.isValid())
//		{
//			super.addReaction(rf);
//		}
//		else
//		{
//			this.removedReactions.add(rf);
//		}
//	}
	
	@Override
	public Collection<C> getCompounds(Reaction<C> reaction) {
		return filter(super.getCompounds(reaction));
	}

	@Override
	public Collection<C> getSubstrats(Reaction<C> reaction) {
		return filter(super.getSubstrats(reaction));
	}

	@Override
	public Collection<C> getProducts(Reaction<C> reaction) {
		return filter(super.getProducts(reaction));
	}

	//
	//	public void addFilteredCompound(C c)
	//	{
	//		filteredMetabolites.add(c);
	//		removedReactions = this.checkReactions();
	//	}
	//
	//	public void removeFilteredCompound(C c)
	//	{
	//		filteredMetabolites.remove(c);
	//		removedReactions = this.checkReactions();
	//	}
	//
	//	public void addFilteredCompounds(Collection<C> filter)
	//	{
	//		filteredMetabolites.addAll(filter);
	//		removedReactions = this.checkReactions();
	//	}
	//
	//	public void removeFilteredCompounds(Collection<C> filter)
	//	{
	//		filteredMetabolites.removeAll(filter);
	//		removedReactions = this.checkReactions();
	//	}

	public void clear()
	{
		super.clear();
		filteredMetabolites.clear();
		removedReactions.clear();
	}

	public static void main(String[] args)
	{
		MetabolicNetworkWithEnzymes<String, Reaction<String>, Protein> meta= new ImplOfMetabolicNetworkWithEnzymes<String, Reaction<String>, Protein>();
		String c1 = "c1";
		meta.addCompound(c1);
		System.out.println("ajout dans meta : "+c1);
		System.out.println("meta : "+meta.toString());
		System.out.println(meta.toString());

		String c2 = "c2", c3 = "c3";
		Collection<String> pg = new HashSet<String>();
		pg.add(c1);
		Collection<String> pd = new HashSet<String>();
		pd.add(c2);pd.add(c3);
		Reaction<String> r1 = new Reaction<String>("r1", pg, pd, ReactionUtil.Orientation.LR);
		System.out.println("ajout dans meta : "+r1);
		meta.addReaction(r1);
		System.out.println("meta : "+meta.toString());
		//		System.out.println("meta.getCompounds(r1) : "+meta.getCompounds(r1).toString());
		//		System.out.println("meta.getReactions(c1) : "+meta.getReactions(c1).toString());
		//		System.out.println("meta.whichConsume(c1) : "+meta.whichConsume(c1).toString());
		//		System.out.println("meta.whichProduce(c1) : "+meta.whichProduce(c1).toString());

		Collection<String> metaboliteCutSet = new HashSet<String>();
		metaboliteCutSet.add(c3);

		String e1 = "e1";
		System.out.println("ajout catalyse : "+e1 +" -- "+ r1);
		Protein p1 = new Protein(e1);
		meta.addCatalyze(p1,r1);
		System.out.println("meta : "+meta.toString());



		System.out.println("copie de meta dans meta2 et meta3");
		MetabolicNetworkWithEnzymes<String, Reaction<String>, Protein> meta2 = new ImplOfMetabolicNetworkWithEnzymes<String, Reaction<String>, Protein>(meta);
		MetabolicNetworkWithEnzymes<String, Reaction<String>, Protein> meta3 = new ImplOfFilteredMetabolicNetworkWithEnzymes<String, Reaction<String>, Protein>(meta, metaboliteCutSet);
		System.out.println("meta : "+meta.toString());
		System.out.println("meta2 : "+meta2.toString());
		System.out.println("meta3 : "+meta3.toString());
		//		System.out.println("meta3.getCompounds(r1) : "+meta3.getCompounds(r1).toString());
		//		System.out.println("meta3.getReactions(c1) : "+meta3.getReactions(c1).toString());
		//		System.out.println("meta3.whichConsume(c1) : "+meta3.whichConsume(c1).toString());
		//		System.out.println("meta3.whichProduce(c1) : "+meta3.whichProduce(c1).toString());

		System.out.println("retrait de meta3 : "+c1);
		meta3.removeCompound(c1);
		System.out.println("meta : "+meta.toString());
		System.out.println("meta2 : "+meta2.toString());
		System.out.println("meta3 : "+meta3.toString());

		System.out.println("retrait de meta : "+c1);
		meta.removeCompound(c1);
		System.out.println("meta : "+meta.toString());
		System.out.println("meta2 : "+meta2.toString());

		System.out.println("test si e1 ne catalyse plus r1 dans meta");
		System.out.println("meta : "+meta.getCatalysedReactions(p1).toString());


		System.out.println("retrait de meta 2 : "+r1);
		meta2.removeReaction(r1);
		System.out.println("meta : "+meta.toString());
		System.out.println("meta2 : "+meta2.toString());

		System.out.println("clear de meta 2 : "+r1);
		meta2.clear();
		System.out.println("meta : "+meta.toString());
		System.out.println("meta2 : "+meta2.toString());
	}

}
